package universum.ui;

import universum.engine.GameInfo;
import universum.engine.Universe;
import universum.engine.ScoreData;
import universum.engine.TempPublicUniverse;
import universum.util.Statistics;
import universum.util.ioUtility;

public class HeadlessController implements GameOwner {
    private Universe universe;
    private GameInfo gi;
    private int port;
    private Object waiter = new Object();
    private volatile boolean done;
    private Statistics stats = Statistics.getInstance();
    private ioUtility io = ioUtility.getInstance();

    public HeadlessController(GameInfo gameInfo, int port) {
        this.port = port;
        this.gi = gameInfo;
    }

    public void startGame(String[][] beings) {
        done = false;
        gi.turnDelay = 0;
        //gi.out = null;
        universe = new Universe(this, gi);
        // TODO: refactor next line
        TempPublicUniverse.getInstance().setUniverse(universe);
        universe.addBeings(beings);
        universe.bigbang();

        long started = System.currentTimeMillis();
        try {
            // and then wait till completion
            synchronized (waiter) {
                while (!done) {
                    waiter.wait(10000);
                    if (System.currentTimeMillis() - started > 1000 * 60 * 60) {
                        universe.stop();
                    }
                }
            }
        } catch (InterruptedException ie) {
            io.writelnError(ie);
        }
        finally
        {
            universe.apocalypse();
            universe = null;
        }
    }

    public void redraw() {
    }

    public void notifyAboutCompletion(GameResult gr) {
        universe.setPaused(true);
        //TODO: replace hardcoding with string.Format
        io.writelnInfo("Game " + gr.kind() + " finished in " + gr.numTurns() + " turns");
        io.writelnInfo("Player\t\tScore\t\tEnergy");
        io.writelnInfo("---------------------------------------");
        io.writeInfo(gr.toString());
        io.writelnInfo("---------------------------------------");

                 for (ScoreData r : gr.results()) {
            stats.addReport("average mass: ", r.score, Statistics.AggregationType.avg);
            stats.addReport("maximum mass: ", r.score, Statistics.AggregationType.max);
            stats.addReport("minimum mass: ", r.score, Statistics.AggregationType.min);
            stats.addReport("average energy: ", r.energy, Statistics.AggregationType.avg);
            stats.addReport("maximum energy: ", r.energy, Statistics.AggregationType.max);
            stats.addReport("minimum energy: ", r.energy, Statistics.AggregationType.min);
        }

        synchronized (waiter) {
            done = true;
            waiter.notify();
        }
    }


    public void setListenPort(int port) {
        this.port = port;
    }

    public int getListenPort() {
        return port;
    }

    public void notifyOnTurnEnd() {
    }
}
